home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fritz: All Fritz
/
All Fritz.zip
/
All Fritz
/
FILES
/
MUSIUSIC
/
PLAYERS.LZH
/
VOC_PC.PKG
< prev
next >
Wrap
Text File
|
1991-01-07
|
4KB
|
111 lines
with calendar;
with rtext_io;
package body voc_pc is
procedure halve(voice_block : in out voice_blocks;
automatic_gain_control : in boolean:=true) is
function "="(left,right:in voc_data.block_types) return boolean
renames voc_data."=";
function "="(left,right:in voc_data.pack_types) return boolean
renames voc_data."=";
-- how long to wait before turning volume louder or softer
turn_louder_lag:constant duration:=0.2; -- be slow to turn up
turn_softer_lag:constant duration:=0.02; -- but fast to turn down
a,b:integer;
err:integer:=0;
subtype multiplier_range is integer range 4 .. 32;
multiplier:multiplier_range:=8; -- starting multiplier
volume_adjustment_point:constant integer
:=integer(voice_block.sample_rate*turn_louder_lag);
too_loud_delta:constant integer
:=integer(turn_louder_lag/turn_softer_lag);
error_level:integer:=0;
j:integer:=1;
begin
if voice_block.packing /= voc_data.unpacked then return;end if;
voice_block.packing:=voc_data.halved;
voice_block.block_length:=(voice_block.block_length-1)/2;
for i in 1 .. voice_block.block_length loop
a:=(integer(voice_block.data(j+1))-integer(voice_block.data(j)))
*multiplier+128+err;
if a < 0 then
err:=a;a:=0;
error_level:=error_level+too_loud_delta;
elsif a > 255 then
err:=a-255;a:=255;
error_level:=error_level+too_loud_delta;
else
error_level:=error_level-1;
err:=0;
end if;
j:=j+1;
b:=(integer(voice_block.data(j+1))-integer(voice_block.data(j)))
*multiplier+128+err;
if b < 0 then
err:=b;b:=0;
error_level:=error_level+too_loud_delta;
elsif b > 255 then
err:=b-255;b:=255;
error_level:=error_level+too_loud_delta;
else
error_level:=error_level-1;
err:=0;
end if;
j:=j+1;
if automatic_gain_control then
if error_level >= volume_adjustment_point then
if multiplier > multiplier_range'first then
multiplier:=multiplier-1;
end if;
error_level:=0;
elsif error_level <= -volume_adjustment_point then
if multiplier < multiplier_range'last then
multiplier:=multiplier+1;
end if;
error_level:=0;
end if;
else
error_level:=0;
end if;
a:=(a+7)/16;
b:=(b+7)/16;
if a > 15 then a:=15;end if;
if b > 15 then b:=15;end if;
if a < 8 then a:=15-a;else a:=a-8;end if;
if b < 8 then b:=15-b;else b:=b-8;end if;
voice_block.data(i):=voc_data.sound_bytes(a*16+b);
end loop;
end halve;
procedure play(voc_block:in out VOC_data.blocks) is
function "="(left,right:in voc_data.block_types) return boolean
renames voc_data."=";
function "="(left,right:in voc_data.pack_types) return boolean
renames voc_data."=";
begin
if voc_block.block_type = voc_data.silence then
declare -- poll for key press for appropriate duration
use calendar;
time_to_stop:constant calendar.time
:=calendar.clock+voc_block.silence_interval;
begin
while calendar.clock < time_to_stop loop
exit when rtext_io.keypress;
end loop;
end;
return;
end if;
if voc_block.block_type /= voc_data.voice_data then
return;
end if;
pc_sound.set_sample_rate(voc_block.sample_rate);
if voc_block.packing=voc_data.unpacked then
halve(voc_block);
end if;
-- other packing styles may generate gibberish
pc_sound.playback(voc_block.data(1)'address,voc_block.block_length);
end play;
end voc_pc;